package com.powerbank.common.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 地理位置工具类
 */
public class GeoUtils {

    // 地球半径（米）
    private static final double EARTH_RADIUS = 6371000;

    /**
     * 计算两个经纬度点之间的距离（米）
     *
     * @param lng1 经度1
     * @param lat1 纬度1
     * @param lng2 经度2
     * @param lat2 纬度2
     * @return 距离（米）
     */
    public static double calculateDistance(double lng1, double lat1, double lng2, double lat2) {
        double radLat1 = Math.toRadians(lat1);
        double radLat2 = Math.toRadians(lat2);
        double deltaRadLat = Math.toRadians(lat2 - lat1);
        double deltaRadLng = Math.toRadians(lng2 - lng1);

        double a = Math.sin(deltaRadLat / 2) * Math.sin(deltaRadLat / 2) +
                Math.cos(radLat1) * Math.cos(radLat2) *
                        Math.sin(deltaRadLng / 2) * Math.sin(deltaRadLng / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return EARTH_RADIUS * c;
    }

    /**
     * 根据中心点和半径计算经纬度边界
     *
     * @param longitude 中心点经度
     * @param latitude  中心点纬度
     * @param radius    半径（米）
     * @return BigDecimal数组，包含[最小经度, 最大经度, 最小纬度, 最大纬度]
     */
    public static BigDecimal[] calculateBounds(BigDecimal longitude, BigDecimal latitude, Integer radius) {
        // 纬度每度距离约111公里
        double latDegreeDistance = 111000.0;
        // 经度每度距离随纬度变化
        double lngDegreeDistance = 111000.0 * Math.cos(Math.toRadians(latitude.doubleValue()));

        // 计算半径对应的经纬度差值
        double latDelta = radius / latDegreeDistance;
        double lngDelta = radius / lngDegreeDistance;

        BigDecimal minLng = longitude.subtract(BigDecimal.valueOf(lngDelta)).setScale(7, RoundingMode.HALF_UP);
        BigDecimal maxLng = longitude.add(BigDecimal.valueOf(lngDelta)).setScale(7, RoundingMode.HALF_UP);
        BigDecimal minLat = latitude.subtract(BigDecimal.valueOf(latDelta)).setScale(7, RoundingMode.HALF_UP);
        BigDecimal maxLat = latitude.add(BigDecimal.valueOf(latDelta)).setScale(7, RoundingMode.HALF_UP);

        return new BigDecimal[]{minLng, maxLng, minLat, maxLat};
    }
}